home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
morse
/
staton
/
adpcm2.c
next >
Wrap
C/C++ Source or Header
|
1994-04-21
|
21KB
|
828 lines
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/* Copyright (C) 1994 Ken Staton */
/* All Rights Reserved */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*
** This program computes an adaptive quantized
** differential PCM version for speech data
** reduction. It processes binary files.
** To use with SoundBlaster, first strip the *.VOC header.
** (see VOC2BIN.C)
*/
/*
** Assume DC start level is mid-range at $80.
** This is a good assumption for properly biased digitized speech.
** Define encoding:
** 2's ABS REL
** -1 $FF +127 Most positive value
** *
** -127 $81 +1 Least positive value
** -128 $80 0 DC level
** +127 $7F -1 Least negative value
** *
** 0 $00 -128 Most negative value
**
** Process signed REL data, since the differential encoding is signed.
** The sampled data is originally in ABS format with an offset of $80,
** i.e. the DC level is $80.
**
** Convert from ABS to REL using signed arithmetic (ABS in 2's form):
** if (ABS >= $80) REL=ABS-($80) {ie REL=ABS-(-128)}
** if (ABS < $80) REL=ABS+($80) {ie REL=ABS+(-128)}
**
** Alternate conversion: REL=(ABS MOD 256) - 128
**
** Convert back to ABS during decode before output to DAC.
*/
#define BLK_SIZE 64 /* MUST be an even number */
#define TRUE 1
#define FALSE 0
/*
** The packed file format is:
** Qfn | d1 Byte1
** d2 | d3 Byte2
** d4 | d5 Byte3
** . | .
** . | .
** . | .
** d60 | d61 Byte31
** d62 | d63 Byte32
**
** The first difference is between the previous value and Data1.
** The last data (Data_N_; N=BLK_SIZE) is the previous value for
** the next block.
*/
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
/* GLOBALS */
FILE *infile, *outfile, *testfile;
char sf[255],tf[255];
char report;
void main(argc,argv)
int argc;
char *argv[];
{
char response;
unsigned int blk;
unsigned char i;
signed char byte[256];
signed char prev;
/*unsigned char Qfn;*/
/* function definitions */
signed char ABS2REL(signed char byte);
signed char quant1(signed char byte);
signed char quant2(signed char byte);
signed char quant3(signed char byte);
signed char quant4(signed char byte);
signed char quant5(signed char byte);
signed char quant6(signed char byte);
signed char quant7(signed char byte);
signed char iq1(signed char byte);
signed char iq2(signed char byte);
signed char iq3(signed char byte);
signed char iq4(signed char byte);
signed char iq5(signed char byte);
signed char iq6(signed char byte);
signed char iq7(signed char byte);
void process_blk(signed char byte[],
unsigned char size,
signed char *prev,
FILE *outfile);
/* code starts here... */
_wabout("Converts binary files to ADPCM.\nCopyright (C) 1994 Ken Staton.\nAll Rights Reserved.\n");
if (argc != 3)
{
printf("Enter the source file: \n");
scanf("%s",sf);
printf("Enter the target file: \n");
scanf("%s",tf);
report = FALSE; /* assume no report */
_wsetexit(_WINEXITNOPERSIST); /* assume no persistence */
printf("Statistics report (y/n)? ");
scanf("%s",&response);
if ((response == 'Y') | (response == 'y'))
{
report = TRUE;
_wsetexit(_WINEXITPERSIST); /* persist if report generated */
}
printf("\n\n");
}
else
{
strcpy(sf,argv[1]);
strcpy(tf,argv[2]);
report = FALSE; /* assume no report */
_wsetexit(_WINEXITNOPERSIST); /* assume no persistence */
}
/* OPEN FILES */
/* Open for read (will fail if source file does not exist) */
if( (infile = fopen( sf, "rb" )) == NULL )
{
printf( "The file %s was not opened\n",sf );
exit(-1);
}
else
{
printf( "The file %s was opened\n",sf );
}
/* Open for write */
/* test for overwrite! */
if( (testfile = fopen( tf, "rb")) != NULL)
{
printf("%s Exists! OVERWRITE (y/n)?",tf);
scanf("%s",&response);
if ((response!='Y') && (response!='y')) exit(-1);
if( fclose( testfile ) ) printf( "The file %s was not closed\n",tf );
printf("\n\n");
}
/* go ahead and create new file */
if( (outfile = fopen( tf, "w+b" )) == NULL )
{
printf( "The file %s was not opened\n",tf );
exit(-1);
}
else
{
printf( "The file %s was opened\n",tf );
}
/* PROCESS FILE */
blk=1; /* count blocks */
i=1; /* start new block */
(unsigned char)prev=0x00; /* assume DC start value REL value! */
byte[i++]=fgetc(infile);
while (feof(infile) == 0)
{
/* get ALL data points in a block before processing. */
/* the fget is at the end of the while loop, */
/* with post increment of i, so the test is BLK_SIZE */
/* which is really an odd number of bytes fetched, */
/* = BLK_SIZE-1, since indexed from 1 instead of 0. */
if (i==BLK_SIZE)
{ /* begin processing block */
if (report) printf("BLK # %4i\n",blk);
process_blk(byte,i,&prev,outfile);
blk++;
i=1; /* start new block */
} /* end processing block */
byte[i++]=fgetc(infile);
} /* end while !EOF */
/* partial block to be processed */
if (i>1)
{ /* begin processing partial block */
if (report)
{
printf("BLK # %4i\n",blk);
printf("Last BLK. %i bytes.\n",i);
}
if ((i%2)) i-=1; /* if even, throw away last byte */
process_blk(byte,i,&prev,outfile);
} /* end processing partial block */
/* Close streams */
if( fclose( infile ) )
printf( "The file %s was not closed\n",sf );
if( fclose( outfile ) )
printf( "The file %s was not closed\n",tf );
} /* END MAIN */
/*
**
** SUBROUTINES
**
*/
/* Block processing... */
void process_blk(signed char byte[],
unsigned char size,
signed char *prev,
FILE *outfile)
{
unsigned char pack;
unsigned int i;
unsigned char Qfn;
unsigned char diff;
signed char p;
signed char pp,pn;
int d,m,v;
double s;
p=*prev;
for (i=1;i<size;i++) /* convert to REL data */
{
byte[i]=ABS2REL(byte[i]);
}
pp=pn=0;
m=0;
for (i=1;i<size;i++) /* peak and mean*/
{
d=(byte[i]-p);
if ((d>=0) && (pp<d)) pp=d; /* pos peak */
if ((d<0) && (pn>d)) pn=d; /* neg peak */
m=m+d; /* mean */
p=byte[i];
}
m=m/i;
v=0;
for (i=1;i<size;i++) /* variance */
{
d=(byte[i]-m);
v=v+(d*d);
}
v=v/i;
s=sqrt(v); /* standard deviation */
if (report)
{
printf("ave = %4i\tvar = %4i\tsd = %4i\n",m,v,(int)s);
}
/* Select Qfn. 4 bits available, but one reserved */
/* for end marker (0000). */
/* PEAK VALUE based Qfn selection. */
if ((pp < 8) && (pn >= -8)) Qfn = 1;
else if ((pp <16) && (pn >= -16)) Qfn = 2;
else if ((pp <32) && (pn >= -32)) Qfn = 3;
else if ((pp <48) && (pn >= -48)) Qfn = 4;
else if ((pp <64) && (pn >= -64)) Qfn = 5;
else if ((pp <96) && (pn >= -96)) Qfn = 6;
else Qfn = 7;
if (report) printf("Qfn = %2i\n\n",Qfn);
byte[0]=Qfn; /* Put Qfn at index zero. */
/* Will still have an even number, */
/* since there are N-1 differences. */
for (i=1;i<size;i++) /* quantize in-place */
{
diff = byte[i] - *prev;
if (Qfn==1)
{
byte[i]=quant1(diff);
*prev = *prev+iq1(byte[i]);
}
if (Qfn==2)
{
byte[i]=quant2(diff);
*prev = *prev+iq2(byte[i]);
}
if (Qfn==3)
{
byte[i]=quant3(diff);
*prev = *prev+iq3(byte[i]);
}
if (Qfn==4)
{
byte[i]=quant4(diff);
*prev = *prev+iq4(byte[i]);
}
if (Qfn==5)
{
byte[i]=quant5(diff);
*prev = *prev+iq5(byte[i]);
}
if (Qfn==6)
{
byte[i]=quant6(diff);
*prev = *prev+iq6(byte[i]);
}
if (Qfn==7)
{
byte[i]=quant7(diff);
*prev = *prev+iq7(byte[i]);
}
}
for (i=0;i<size;i+=2) /* pack & output */
{
pack=((byte[i]<<4)|(byte[i+1]&0X0F));
fputc(pack,outfile);
}
} /* end process */
/*
** Absolute to relative conversion subroutine
*/
signed char ABS2REL(signed char byte)
{
signed char REL;
if ((unsigned char)byte >= 128)
REL = byte + 128;
else
REL = byte - 128;
return(REL);
}
/*
**
** Quantization routines follow.
**
** The result of quatization is always 8 bits signed (signed char),
** but really interested in 4 bit signed.
**
** Dec Bin (2's C)
** 7 0000 0111
** 6 0000 0110
** 5 0000 0101
** 4 0000 0100
** 3 0000 0011
** 2 0000 0010
** 1 0000 0001
** 0 0000 0000
** -1 1111 1111
** -2 1111 1110
** -3 1111 1101
** -4 1111 1100
** -5 1111 1011
** -6 1111 1010
** -7 1111 1001
** -8 1111 1000
**
** Note that the 4 bit 2's complement can be obtained simply by
** ignoring the upper 4 bits of the 8 bit 2's complement.
**
*/
/*****************************************************/
signed char quant1(signed char byte)
{
/* linear */
signed char qb;
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=2;
if (byte==3) qb=3;
if (byte==4) qb=4;
if (byte==5) qb=5;
if (byte==6) qb=6;
if (byte>=7) qb=7;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if (byte==-3) qb=-3;
if (byte==-4) qb=-4;
if (byte==-5) qb=-5;
if (byte==-6) qb=-6;
if (byte==-7) qb=-7;
if (byte<=-8) qb=-8;
if (report)
{
if (qb==7)
printf("QByte max pos (+7) in Q1. Byte = %i\n",byte);
if (qb==-8)
printf("QByte max neg (-8) in Q1. Byte = %i\n",byte);
}
return(qb);
}
/*****************************************************/
signed char quant2(signed char byte)
{
signed char qb;
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=2;
if (byte==3) qb=3;
if ((byte>=4) && (byte<6)) qb=4;
if ((byte>=6) && (byte<8)) qb=5;
if ((byte>=8) && (byte<12)) qb=6;
if (byte>=12) qb=7;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if (byte==-3) qb=-3;
if (byte==-4) qb=-4;
if ((byte<=-5) && (byte>-7)) qb=-5;
if ((byte<=-7) && (byte>-10)) qb=-6;
if ((byte<=-10) && (byte>-13)) qb=-7;
if (byte<=-13) qb=-8;
if (report)
{
if (qb==7)
printf("QByte max pos (+12) in Q2. Byte = %i\n",byte);
if (qb==-8)
printf("QByte max neg (-13) in Q2. Byte = %i\n",byte);
}
return(qb);
}
signed char quant3(signed char byte)
{
signed char qb;
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=2;
if ((byte>=3) && (byte<6)) qb=3;
if ((byte>=6) && (byte<9)) qb=4;
if ((byte>=9) && (byte<15)) qb=5;
if ((byte>=15) && (byte<24)) qb=6;
if (byte>=24) qb=7;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if ((byte<=-3) && (byte>-5)) qb=-3;
if ((byte<=-5) && (byte>-7)) qb=-4;
if ((byte<=-7) && (byte>-11)) qb=-5;
if ((byte<=-11) && (byte>-17)) qb=-6;
if ((byte<=-17) && (byte>-26)) qb=-7;
if (byte<=-26) qb=-8;
if (report)
{
if (qb==7)
printf("QByte max pos (+24) in Q3. Byte = %i\n",byte);
if (qb==-8)
printf("QByte max neg (-26) in Q3. Byte = %i\n",byte);
}
return(qb);
}
signed char quant4(signed char byte)
{
signed char qb;
if (byte==0) qb=0;
if (byte==1) qb=1;
if ((byte>=2) && (byte<4)) qb=2;
if ((byte>=4) && (byte<7)) qb=3;
if ((byte>=7) && (byte<12)) qb=4;
if ((byte>=12) && (byte<21)) qb=5;
if ((byte>=21) && (byte<36)) qb=6;
if (byte>=36) qb=7;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if ((byte<=-3) && (byte>-5)) qb=-3;
if ((byte<=-5) && (byte>-9)) qb=-4;
if ((byte<=-9) && (byte>-14)) qb=-5;
if ((byte<=-14) && (byte>-23)) qb=-6;
if ((byte<=-23) && (byte>-38)) qb=-7;
if (byte<=-38) qb=-8;
if (report)
{
if (qb==7)
printf("QByte max pos (+36) in Q4. Byte = %i\n",byte);
if (qb==-8)
printf("QByte max neg (-38) in Q4. Byte = %i\n",byte);
}
return(qb);
}
/*****************************************************/
signed char quant5(signed char byte)
{
/* linear */
signed char qb;
if (byte==0) qb=0;
if (byte==1) qb=1;
if ((byte>=2) && (byte<4)) qb=2;
if ((byte>=4) && (byte<8)) qb=3;
if ((byte>=8) && (byte<14)) qb=4;
if ((byte>=14) && (byte<26)) qb=5;
if ((byte>=26) && (byte<47)) qb=6;
if (byte>=47) qb=7;
if (byte==-1) qb=-1;
if ((byte<=-2) && (byte>-4)) qb=-2;
if ((byte<=-4) && (byte>-6)) qb=-3;
if ((byte<=-6) && (byte>-10)) qb=-4;
if ((byte<=-10) && (byte>-17)) qb=-5;
if ((byte<=-17) && (byte>-29)) qb=-6;
if ((byte<=-29) && (byte>-49)) qb=-7;
if (byte<=-49) qb=-8;
if (report)
{
if (qb==7)
printf("QByte max pos (+47) in Q5. Byte = %i\n",byte);
if (qb==-8)
printf("QByte max neg (-49) in Q5. Byte = %i\n",byte);
}
return(qb);
}
/*****************************************************/
signed char quant6(signed char byte)
{
/* linear */
signed char qb;
if (byte==0) qb=0;
if ((byte>=1) && (byte<3)) qb=1;
if ((byte>=3) && (byte<5)) qb=2;
if ((byte>=5) && (byte<10)) qb=3;
if ((byte>=10) && (byte<19)) qb=4;
if ((byte>=19) && (byte<36)) qb=5;
if ((byte>=36) && (byte<69)) qb=6;
if (byte>=69) qb=7;
if (byte==-1) qb=-1;
if ((byte<=-2) && (byte>-4)) qb=-2;
if ((byte<=-4) && (byte>-7)) qb=-3;
if ((byte<=-7) && (byte>-13)) qb=-4;
if ((byte<=-13) && (byte>-23)) qb=-5;
if ((byte<=-23) && (byte>-41)) qb=-6;
if ((byte<=-41) && (byte>-72)) qb=-7;
if (byte<=-72) qb=-8;
if (report)
{
if (qb==7)
printf("QByte max pos (+69) in Q6. Byte = %i\n",byte);
if (qb==-8)
printf("QByte max neg (-72) in Q6. Byte = %i\n",byte);
}
return(qb);
}
/*****************************************************/
signed char quant7(signed char byte)
{
/* linear */
signed char qb;
if (byte==0) qb=0;
if ((byte>=1) && (byte<3)) qb=1;
if ((byte>=3) && (byte<6)) qb=2;
if ((byte>=6) && (byte<11)) qb=3;
if ((byte>=11) && (byte<23)) qb=4;
if ((byte>=23) && (byte<45)) qb=5;
if ((byte>=45) && (byte<90)) qb=6;
if (byte>=90) qb=7;
if (byte==-1) qb=-1;
if ((byte<=-2) && (byte>-5)) qb=-2;
if ((byte<=-5) && (byte>-8)) qb=-3;
if ((byte<=-8) && (byte>-15)) qb=-4;
if ((byte<=-15) && (byte>-28)) qb=-5;
if ((byte<=-28) && (byte>-52)) qb=-6;
if ((byte<=-52) && (byte>-95)) qb=-7;
if (byte<=-95) qb=-8;
if (report)
{
if (qb==7)
printf("QByte max pos (+90) in Q7. Byte = %i\n",byte);
if (qb==-8)
printf("QByte max neg (-95) in Q7. Byte = %i\n",byte);
}
return(qb);
}
/*****************************************************/
/*****************************************************/
/* input to these inverse quantizers is 8 bits. */
/* select minimum value in ranges... */
signed char iq1(signed char byte)
{
signed char qb;
if (report) if (!((byte<8)&&(byte>-9))) printf("ERROR: Byte range. Byte = %i\n",byte);
/* linear */
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=2;
if (byte==3) qb=3;
if (byte==4) qb=4;
if (byte==5) qb=5;
if (byte==6) qb=6;
if (byte==7) qb=7;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if (byte==-3) qb=-3;
if (byte==-4) qb=-4;
if (byte==-5) qb=-5;
if (byte==-6) qb=-6;
if (byte==-7) qb=-7;
if (byte==-8) qb=-8;
return(qb);
}
/*****************************************************/
signed char iq2(signed char byte)
{
signed char qb;
if (report) if (!((byte<8)&&(byte>-9))) printf("ERROR: Byte range. Byte = %i\n",byte);
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=2;
if (byte==3) qb=3;
if (byte==4) qb=4;
if (byte==5) qb=6;
if (byte==6) qb=8;
if (byte==7) qb=12;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if (byte==-3) qb=-3;
if (byte==-4) qb=-4;
if (byte==-5) qb=-5;
if (byte==-6) qb=-7;
if (byte==-7) qb=-10;
if (byte==-8) qb=-13;
return(qb);
}
signed char iq3(signed char byte)
{
signed char qb;
if (report) if (!((byte<8)&&(byte>-9))) printf("ERROR: Byte range. Byte = %i\n",byte);
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=2;
if (byte==3) qb=3;
if (byte==4) qb=6;
if (byte==5) qb=9;
if (byte==6) qb=15;
if (byte==7) qb=24;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if (byte==-3) qb=-3;
if (byte==-4) qb=-5;
if (byte==-5) qb=-7;
if (byte==-6) qb=-11;
if (byte==-7) qb=-17;
if (byte==-8) qb=-26;
return(qb);
}
signed char iq4(signed char byte)
{
signed char qb;
if (report) if (!((byte<8)&&(byte>-9))) printf("ERROR: Byte range. Byte = %i\n",byte);
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=2;
if (byte==3) qb=4;
if (byte==4) qb=7;
if (byte==5) qb=12;
if (byte==6) qb=21;
if (byte==7) qb=36;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if (byte==-3) qb=-3;
if (byte==-4) qb=-5;
if (byte==-5) qb=-9;
if (byte==-6) qb=-14;
if (byte==-7) qb=-23;
if (byte==-8) qb=-38;
return(qb);
}
/*****************************************************/
signed char iq5(signed char byte)
{
signed char qb;
if (report) if (!((byte<8)&&(byte>-9))) printf("ERROR: Byte range. Byte = %i\n",byte);
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=2;
if (byte==3) qb=4;
if (byte==4) qb=8;
if (byte==5) qb=14;
if (byte==6) qb=26;
if (byte==7) qb=47;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if (byte==-3) qb=-4;
if (byte==-4) qb=-6;
if (byte==-5) qb=-10;
if (byte==-6) qb=-17;
if (byte==-7) qb=-29;
if (byte==-8) qb=-49;
return(qb);
}
/*****************************************************/
signed char iq6(signed char byte)
{
signed char qb;
if (report) if (!((byte<8)&&(byte>-9))) printf("ERROR: Byte range. Byte = %i\n",byte);
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=3;
if (byte==3) qb=5;
if (byte==4) qb=10;
if (byte==5) qb=19;
if (byte==6) qb=36;
if (byte==7) qb=69;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if (byte==-3) qb=-4;
if (byte==-4) qb=-7;
if (byte==-5) qb=-13;
if (byte==-6) qb=-23;
if (byte==-7) qb=-41;
if (byte==-8) qb=-72;
return(qb);
}
/*****************************************************/
signed char iq7(signed char byte)
{
signed char qb;
if (report) if (!((byte<8)&&(byte>-9))) printf("ERROR: Byte range. Byte = %i\n",byte);
/* linear */
if (byte==0) qb=0;
if (byte==1) qb=1;
if (byte==2) qb=3;
if (byte==3) qb=6;
if (byte==4) qb=11;
if (byte==5) qb=23;
if (byte==6) qb=45;
if (byte==7) qb=90;
if (byte==-1) qb=-1;
if (byte==-2) qb=-2;
if (byte==-3) qb=-5;
if (byte==-4) qb=-8;
if (byte==-5) qb=-15;
if (byte==-6) qb=-28;
if (byte==-7) qb=-52;
if (byte==-8) qb=-95;
return(qb);
}
/*****************************************************/